#include <Windows.h>
#include <tchar.h>
#include "resource.h"
#include <WindowsX.h>

#define CHANNELBUFSIZE			(64 * 1024)

#define	SENDCHANNEL				_T("DemoEX")
#define	RECEIVECHANNEL			_T("Demo")

#define EVENTQUITDEMOEX			_T("QUIT_DEMOEX")
#define EVENTDEMOEXRAN			_T("DEMOEX_RAN")

#define EVENTDEMORAN			_T("DEMO_RAN")
#define EVENTDEMOQUITED			_T("DEMO_QUITED")

#define EVENTRECEIVET			_T("DEMO_MESSAGE")
#define EVENTSEND				_T("DEMOEX_MESSAGE")


DWORD CALLBACK ThreadProc(LPVOID lpData)
{
	HWND hLstInfo = (HWND)lpData;
	HANDLE hEvtMonitor[2] = {CreateEvent(NULL, FALSE, FALSE, EVENTQUITDEMOEX), CreateEvent(NULL, TRUE, FALSE, EVENTDEMORAN)};
	DWORD nIndex = WaitForMultipleObjects(2, hEvtMonitor, FALSE, INFINITE);
	if (1 == nIndex) 
	{
		ResetEvent(hEvtMonitor[1]);

		bool bQuit = false;
		HANDLE hEvents[2] = { CreateEvent(NULL, FALSE, FALSE, EVENTQUITDEMOEX), CreateEvent(NULL, FALSE, FALSE, EVENTRECEIVET) };
		HANDLE hFileMapping	= OpenFileMapping(PAGE_READWRITE, FALSE, RECEIVECHANNEL);
		if (NULL != hFileMapping)
		{		
			while (!bQuit)
			{
				DWORD nIndex = WaitForMultipleObjects(2, hEvents,  FALSE, INFINITE);
				switch (nIndex)
				{
					case 0:		
					{
						bQuit = true;		
						break;
					}
					case 1:
					{
						TCHAR* pMapView = (TCHAR*)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, CHANNELBUFSIZE);
						if (NULL != pMapView)
						{
							TCHAR szInfo[CHANNELBUFSIZE + 32];
							_stprintf(szInfo, _T("Demo: %s"), pMapView);
							ListBox_AddString(hLstInfo, szInfo);
						}
						UnmapViewOfFile(pMapView);
					}
				}
			}
			CloseHandle(hFileMapping);
		}
	}
	return 0;
}

int CALLBACK DlgProc(HWND hDlg, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	static HANDLE hThread		= NULL;
	static HANDLE hFileMapping	= NULL;
	static HANDLE hEvtRan		= NULL; 
	static HANDLE hEvtMsg		= NULL;

	switch (nMsg)
	{
		case WM_INITDIALOG:
		{
			SetWindowText(hDlg, _T("Demo0115Ex"));

			UINT nWidth		= GetSystemMetrics(SM_CXSCREEN);
			UINT nHeight	= GetSystemMetrics(SM_CYSCREEN);
			RECT rtClient;
			GetClientRect(hDlg, &rtClient);
			SetWindowPos(hDlg, NULL, (nWidth - (rtClient.right - rtClient.left)) / 2, (nHeight - (rtClient.bottom - rtClient.top)) / 2, 0, 0, SWP_NOSIZE);
			
			hFileMapping	= CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, CHANNELBUFSIZE & 0xFFFFFFFF, SENDCHANNEL);
			if (NULL != hFileMapping)
			{
				hEvtRan = CreateEvent(NULL, TRUE, TRUE, EVENTDEMOEXRAN);
				SetEvent(hEvtRan);
			}
			hThread	= CreateThread(NULL, 0, ThreadProc, GetDlgItem(hDlg, IDC_LSTINFOS), NULL, NULL);
		
			hEvtMsg = CreateEvent(NULL, FALSE, FALSE, EVENTSEND);

			break;
		}
		case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
				case IDC_BTNSEND:
				{
					TCHAR szMsg[CHANNELBUFSIZE];
					Edit_GetText(GetDlgItem(hDlg, IDC_EDTMSG), szMsg, _countof(szMsg));
					
					TCHAR* pMapView = (TCHAR*)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, CHANNELBUFSIZE & 0XFFFFFFFF);
					if (NULL != pMapView)
					{	
						_tcscpy(pMapView, szMsg);
						UnmapViewOfFile(pMapView);
						SetEvent(hEvtMsg);
					}
						
					TCHAR szInfo[CHANNELBUFSIZE + 32];
					_stprintf(szInfo, _T("DemoEx: %s"), szMsg);
					ListBox_AddString(GetDlgItem(hDlg, IDC_LSTINFOS), szInfo);
					Edit_SetText(GetDlgItem(hDlg, IDC_EDTMSG), _T(""));	
				}
			}

			break;
		}
		case WM_CLOSE:
		{
			HANDLE hEvtQuit = CreateEvent(NULL, FALSE, TRUE, EVENTQUITDEMOEX);
			if (NULL != hEvtQuit)
			{
				WaitForSingleObject(hThread, 500);
				CloseHandle(hEvtQuit);
			}
			if (NULL != hEvtRan)
			{
				CloseHandle(hEvtRan);
			}
			if (NULL != hEvtMsg)
			{
				CloseHandle(hEvtMsg);
			}
			if (NULL != hFileMapping)
			{
				CloseHandle(hFileMapping);
			}
			PostQuitMessage(0);
			break;
		}
	}

	return 0;
}

BOOL WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR szCmdLine, int nShowCmd)
{
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);

	return TRUE;
}